package com.example.cameraxapp.utils

import android.app.Activity
import android.content.ContentUris
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.text.TextUtils
import android.util.Log
import com.example.cameraxapp.app.CameraApp.Companion.instance
import java.io.File

/**
 * @auth: njb
 * @date: 2021/10/20 16:54
 * @desc: 文件存储目录管理工具类
 */
object FileManager {
    // 媒体模块根目录
    private val SAVE_MEDIA_ROOT_DIR = Environment.DIRECTORY_DCIM

    // 媒体模块存储路径
    private val SAVE_MEDIA_DIR = SAVE_MEDIA_ROOT_DIR + "/CameraXApp"
    private const val AVATAR_DIR = "/avatar"
    private val SAVE_MEDIA_VIDEO_DIR = SAVE_MEDIA_DIR + "/video"
    private val SAVE_MEDIA_PHOTO_DIR = SAVE_MEDIA_DIR + "/photo"

    // JPG后缀
    const val JPG_SUFFIX = ".jpg"

    // PNG后缀
    const val PNG_SUFFIX = ".png"

    // MP4后缀
    const val MP4_SUFFIX = ".mp4"

    // YUV后缀
    const val YUV_SUFFIX = ".yuv"

    // h264后缀
    const val H264_SUFFIX = ".h264"

    /**
     * 保存图片到系统相册
     *
     * @param context
     * @param file
     */
    fun saveImage(context: Context, file: File): String {
        val localContentResolver = context.contentResolver
        val localContentValues = getImageContentValues(context, file, System.currentTimeMillis())
        localContentResolver.insert(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            localContentValues
        )
        val localIntent = Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE")
        val localUri = Uri.fromFile(file)
        localIntent.data = localUri
        context.sendBroadcast(localIntent)
        return file.absolutePath
    }

    fun getImageContentValues(
        paramContext: Context?,
        paramFile: File,
        paramLong: Long
    ): ContentValues {
        val localContentValues = ContentValues()
        localContentValues.put("title", paramFile.name)
        localContentValues.put("_display_name", paramFile.name)
        localContentValues.put("mime_type", "image/jpeg")
        localContentValues.put("datetaken", java.lang.Long.valueOf(paramLong))
        localContentValues.put("date_modified", java.lang.Long.valueOf(paramLong))
        localContentValues.put("date_added", java.lang.Long.valueOf(paramLong))
        localContentValues.put("orientation", Integer.valueOf(0))
        localContentValues.put("_data", paramFile.absolutePath)
        localContentValues.put("_size", java.lang.Long.valueOf(paramFile.length()))
        return localContentValues
    }

    /**
     * 获取App存储根目录
     */
    val appRootDir: String
        get() {
            val path = storageRootDir
            FileUtil.createOrExistsDir(path)
            return path
        }

    /**
     * 获取文件存储根目录
     */
    val storageRootDir: String
        get() {
            val filePath = instance.getExternalFilesDir("")
            val path: String
            path = if (filePath != null) {
                filePath.absolutePath
            } else {
                instance.filesDir.absolutePath
            }
            return path
        }

    /**
     * 图片地址
     */
    val cameraPhotoPath: String?
        get() = getFolderDirPath(SAVE_MEDIA_PHOTO_DIR)

    /**
     * 获取拍照普通图片文件
     */
    fun getSavedPictureFile(timeStamp: Long): File {
        val fileName = "image" + "_" + +timeStamp + JPG_SUFFIX
        return File(cameraPhotoPath, fileName)
    }

    /**
     * 头像地址
     */
    @JvmStatic
    fun getAvatarPath(fileName: String): String {
        val path: String?
        path = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            getFolderDirPath(SAVE_MEDIA_DIR + AVATAR_DIR)
        } else {
            getSaveDir(AVATAR_DIR)
        }
        return path + File.separator + fileName
    }

    /**
     * 视频地址
     */
    val cameraVideoPath: String?
        get() = getFolderDirPath(SAVE_MEDIA_VIDEO_DIR)

    fun getFolderDirPath(dstDirPathToCreate: String?): String? {
        val dstFileDir = File(Environment.getExternalStorageDirectory(), dstDirPathToCreate)
        if (!dstFileDir.exists() && !dstFileDir.mkdirs()) {
            Log.e("Failed to create file", dstDirPathToCreate!!)
            return null
        }
        return dstFileDir.absolutePath
    }

    /**
     * 获取具体模块存储目录
     */
    fun getSaveDir(directory: String): String {
        var path = ""
        path = if (TextUtils.isEmpty(directory) || "/" == directory) {
            ""
        } else if (directory.startsWith("/")) {
            directory
        } else {
            "/$directory"
        }
        path = appRootDir + path
        FileUtil.createOrExistsDir(path)
        return path
    }

    /**
     * 通过媒体文件Uri获取文件-Android 11兼容
     *
     * @param fileUri 文件Uri
     */
    fun getMediaUri2File(fileUri: Uri?): File? {
        val projection = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = instance.contentResolver.query(
            fileUri!!, projection,
            null, null, null
        )
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
                val path = cursor.getString(columnIndex)
                cursor.close()
                return File(path)
            }
        }
        return null
    }

    /**
     * 根据Uri获取图片绝对路径，解决Android4.4以上版本Uri转换
     *
     * @param context  上下文
     * @param imageUri 图片地址
     */
    fun getImageAbsolutePath(context: Activity?, imageUri: Uri?): String? {
        if (context == null || imageUri == null) return null
        if (DocumentsContract.isDocumentUri(context, imageUri)) {
            if (isExternalStorageDocument(imageUri)) {
                val docId = DocumentsContract.getDocumentId(imageUri)
                val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                val type = split[0]
                if ("primary".equals(type, ignoreCase = true)) {
                    return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                }
            } else if (isDownloadsDocument(imageUri)) {
                val id = DocumentsContract.getDocumentId(imageUri)
                val contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"),
                    id.toLong()
                )
                return getDataColumn(context, contentUri, null, null)
            } else if (isMediaDocument(imageUri)) {
                val docId = DocumentsContract.getDocumentId(imageUri)
                val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                val type = split[0]
                var contentUri: Uri? = null
                if ("image" == type) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                } else if ("video" == type) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                } else if ("audio" == type) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }
                val selection = MediaStore.Images.Media._ID + "=?"
                val selectionArgs = arrayOf(split[1])
                return getDataColumn(context, contentUri, selection, selectionArgs)
            }
        } // MediaStore (and general)
        else if ("content".equals(imageUri.scheme, ignoreCase = true)) {
            // Return the remote address
            return if (isGooglePhotosUri(imageUri)) imageUri.lastPathSegment else getDataColumn(
                context,
                imageUri,
                null,
                null
            )
        } else if ("file".equals(imageUri.scheme, ignoreCase = true)) {
            return imageUri.path
        }
        return null
    }

    /**
     * @param uri The Uri to checkRemote.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    fun isExternalStorageDocument(uri: Uri): Boolean {
        return "com.android.externalstorage.documents" == uri.authority
    }

    /**
     * @param uri The Uri to checkRemote.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    fun isDownloadsDocument(uri: Uri): Boolean {
        return "com.android.providers.downloads.documents" == uri.authority
    }

    /**
     * @param uri The Uri to checkRemote.
     * @return Whether the Uri authority is MediaProvider.
     */
    fun isMediaDocument(uri: Uri): Boolean {
        return "com.android.providers.media.documents" == uri.authority
    }

    /**
     * @param uri The Uri to checkRemote.
     * @return Whether the Uri authority is Google Photos.
     */
    fun isGooglePhotosUri(uri: Uri): Boolean {
        return "com.google.android.apps.photos.content" == uri.authority
    }

    fun getDataColumn(
        context: Context,
        uri: Uri?,
        selection: String?,
        selectionArgs: Array<String>?
    ): String? {
        val column = MediaStore.Images.Media.DATA
        val projection = arrayOf(column)
        context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
            .use { cursor ->
                if (cursor != null && cursor.moveToFirst()) {
                    val index = cursor.getColumnIndexOrThrow(column)
                    return cursor.getString(index)
                }
            }
        return null
    }
}